import React, {Component} from "react";
import './index.css'
import {block_contains, column_contains, init, row_contains} from "./init";
import {message, Modal, Button, Select} from 'antd'

const {Option} = Select
const levels = ['入门', '简单', '中等', '困难',]
const classes = ['cellClick', 'wrongNumber', 'sameNumber']
const STANDARD_ARR = [1, 2, 3, 4, 5, 6, 7, 8, 9]
let timeInterval

function init_game(level) {
    let arr = init(level)
    for (let i = 0; i < arr.length; i++) {
        for (let j = 0; j < arr[i].length; j++) {
            arr[i][j] = {value: arr[i][j], disabled: arr[i][j] !== undefined}
        }
    }
    return arr
}

function findIndex(target, arr) {
    for (let i = 0; i < arr.length; i++) {
        if (arr[i] === target)
            return i
    }
    return undefined
}

function setError(target, error) {
    if (error) {
        target.classList.add(classes[1])
        message.error('填的数字重复了')
    } else {
        target.classList.remove(classes[1])
    }
}

function computeTime(time) {
    let sec = Math.floor(time % 60)
    let min = Math.floor(time / 60)
    return `${min} : ${sec}`
}

export default class Sudoku extends Component {
    state = {
        result: [],
        choose: {i: -1, j: -1},
        hoverTarget: undefined,
        showModal: false,
        level: 1,
        startTime: 0,
    }

    constructor(props) {
        super(props);
        this.table = React.createRef()
    }


    init() {
        this.setState({result: init_game(this.state.level), startTime: 0})
        this.setGrandsonClass()
        clearInterval(timeInterval)
        timeInterval = this.newInterval()
    }

    newInterval() {
        return setInterval(() => {
            let startTime = this.state.startTime + 1
            this.setState({startTime})
        }, 1000)
    }

    componentDidMount() {
        this.init()
    }

    componentWillUnmount() {
        clearInterval(timeInterval)
    }

    setGrandsonClass(target, num, i, j) {
        let grandParent = this.table.current
        if (target) {
            for (let k = 0; k < grandParent.childNodes.length; k++) {
                for (let l = 0; l < grandParent.childNodes[k].childNodes.length; l++) {
                    let temp = grandParent.childNodes[k].childNodes[l].childNodes[0]
                    let number = temp.innerText
                    //相同数字的
                    if (number !== '' && num === number) temp.classList.add(classes[2])
                    else temp.classList.remove(classes[2])
                    // 点击的
                    if (i === k && j === l) temp.classList.add(classes[0])
                    else temp.classList.remove(classes[0])
                }
            }
        } else {
            //清空所有附加的classname
            for (let k = 0; k < grandParent.childNodes.length; k++) {
                for (let l = 0; l < grandParent.childNodes[k].childNodes.length; l++) {
                    let temp = grandParent.childNodes[k].childNodes[l].childNodes[0]
                    temp.classList.remove(...classes)
                }
            }
        }
    }

    clickEle(e) {
        if (e.target.nodeName === 'SPAN') {
            let target = e.target.parentNode, parent = target.parentNode, grandParent = parent.parentNode
            let i = findIndex(parent, grandParent.childNodes)
            let j = findIndex(target, parent.childNodes)
            this.setState({choose: {i, j}})
            this.setGrandsonClass(target, e.target.innerText, i, j)
        }
    }

    chooseNum(e) {
        let {i, j} = this.state.choose
        if (i !== -1 || j !== -1) {
            let num = Number(e.target.innerText)
            let result = this.state.result
            if (result[i][j].disabled) {
                message.warning('这个数字不可更改')
                return
            }
            let target = this.table.current.childNodes[i].childNodes[j].childNodes[0]
            if (row_contains(result[i], num) || column_contains(result, j, num) || block_contains(result, i, j, num)) {
                setError(target, true)
            } else {
                setError(target, false)
            }
            result[i][j].value = num
            this.setState({result})
            this.check()
        }
    }

    clear() {
        let result = this.state.result
        let {i, j} = this.state.choose
        if (result[i][j].value && !result[i][j].disabled) {
            result[i][j].value = undefined
            this.setState({result})
        }
    }

    check() {
        let result = this.state.result
        let hasBlank = false
        for (let i = 0; i < result.length; i++) {
            for (let j = 0; j < result[i].length; j++) {
                if (result[i][j].value === undefined) {
                    hasBlank = true
                    return
                }
            }
        }
        if (!hasBlank) {
            this.setState({showModal: true})
            clearInterval(timeInterval)
            message.success('恭喜完成！')
        }
    }

    nextGame() {
        this.setState({showModal: false})
        this.init()
    }

    nextGameCancel() {
        this.setState({showModal: false})
        timeInterval = this.newInterval()
    }

    chooseLevel(e) {
        this.setState({level: e})
    }

    render() {

        return (<div>
            <Select placeholder="难度" onChange={this.chooseLevel.bind(this)}
                    className="chooseLevel">
                <Option value={1}>{levels[0]}</Option>
                <Option value={2}>{levels[1]}</Option>
                <Option value={3}>{levels[2]}</Option>
                <Option value={4}>{levels[3]}</Option>
            </Select>
            <Button onClick={this.clear.bind(this)} className="clickButton clear">清除</Button>
            <Button onClick={this.init.bind(this)} className="clickButton reset">重置</Button>
            <div className="clickButton timeUsed">{computeTime(this.state.startTime)}</div>
            <div className="table" ref={this.table} onClick={this.clickEle.bind(this)}>
                {this.state.result.map((row_item, row_index) => {
                    return (
                        <div className={row_index % 3 === 0 && row_index > 0 ? 'row line' : 'row'}
                             key={row_index}>
                            {row_item.map((cell_item, cell_index) => {
                                return (
                                    <div className={cell_index % 3 === 0 && cell_index > 0 ? 'cell column' : 'cell'}
                                         key={cell_index}>
                                        <span className="content"> {cell_item.value}</span>
                                    </div>)
                            })}
                        </div>)
                })}
            </div>
            <div id="numbers">
                {STANDARD_ARR.map(item => {
                    return (<span key={item} className="chooseNumber"
                                  onClick={this.chooseNum.bind(this)}>
                                {item}
                            </span>)
                })}
            </div>
            <Modal open={this.state.showModal}
                   title="游戏完成"
                   onOk={this.nextGame.bind(this)}
                   onCancel={this.nextGameCancel.bind(this)}
                   cancelText="取消"
                   okText="重新开始">
                <span>恭喜完成游戏，用时 {computeTime(this.state.startTime)}, 开始下一局吧</span>
            </Modal>
        </div>)
    }
}